import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

import 'package:rxdart/rxdart.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';

import '../component/loading_component.dart';
import '../plugin_import/plugin_import.dart';
import 'component/drag_drop_panel.dart';

///
/// ProjectName: ncmflutterDev
/// Author: lizhi
/// CreateDate: 2022/4/12 10:16 上午
/// Copyright: ©2022 NEW CORE Technology Co. Ltd. All rights reserved.
/// Description: 连续扫描扫码页 T 信息条目Model  已支持PDA连续扫码
/// 扫码框（上半部区域）  右侧从相册选取、自定义icon（默认不显示）
/// customSheetWidget 不为空时 自己完全掌控内容显示
///
/// customSheetWidget 为空时，
/// 信息显示区域（上下拖动信息框高度）
/// 底部确定(xx)按钮，列表为空时会禁用（或自定义的底部widget）
///
/// ps:条目信息数据量比较大时，需要使用InfoListController设置成大数据模式，
/// 大数据模式：true 列表会用Column包裹显示（为确保页面渲染不占用多内存，自定义的条目最好用ListView显示）
///  false 列表用ScrollablePositionedList显示（扫码时会自动触发上滚显示）
/// 展示信息列表控制器
class InfoListController {
  late void Function(dynamic data) remove;
  late void Function(List<dynamic> list) removeList;
  late void Function(int index) removeAt;
  late void Function(int index, dynamic infoItem) replace;
  late void Function(int index, dynamic infoItem) insert;
  late void Function() clearList;
  late bool Function() isEmpty;
  late int Function() listLength;
  late void Function() pauseScan;
  late void Function() resumeScan;
  late void Function(bool value) setScanLock;

  /// 设置大数据模式，列表用Column包裹显示  默认是ScrollablePositionedList包裹
  late void Function(bool isBigDataModel) setBigDataModel;

  ///默认扫码回调处理
  late void Function(String? scanContent) defaultScanHandler;

  ///默认SheetView
  late WidgetBuilder defaultSheetBuilder;
}

class ContinueScanPage<T> extends StatefulWidget {
  const ContinueScanPage({
    Key? key,
    required this.infoListController,
    required this.onScanResult,
    this.customSheetWidget,
    this.getInfoItemWidget,
    this.onConfirm,
    this.customBottomWidget,
    this.initDataList,
    this.onWillPop,
    this.infoHeadWidget,
    this.infoTitleWidget,
    this.titleRightWidget,
    this.rightCustomWidget,
    this.isPDAModel = false,
    this.initScanLock = false,
    this.parseMinInterval = 1500,
    this.autoScrollCount = 3,
    this.title,
    this.infoTitleHeight,
    this.onCustomScanHandler,
    this.onCustomSheetBuilder,
  }) : super(key: key);

  /// 用于控制 展示列表条目 增删改
  final InfoListController infoListController;

  /// 默认填充数据
  final List<T>? initDataList;

  /// 识别结果处理，需要返回条目信息model
  /// showLoading 默认true，批量识别图片时false
  /// infoList 可用于信息防重
  final Future<T?> Function(String result, List<T> infoList, bool showLoading)
      onScanResult;

  /// 自定义sheetWidget(扫码框下面的一整块布局 包含底部按钮区域)  与 getInfoItemWidget、onConfirm、customBottomWidget 互斥
  /// 使用此方法时 无需再用 getInfoItemWidget、onConfirm、customBottomWidget
  final Widget Function(List<T> infoList)? customSheetWidget;

  /// 默认的sheetWidget  信息条目Widget
  final Widget Function(T infoData, int index, int totalLength)?
      getInfoItemWidget;

  /// 默认的sheetWidget 底部按钮 点击底部确认时
  final Function(List<T> infoList)? onConfirm;

  /// 默认的sheetWidget 自定义底部区域按钮Widget 已用SafeArea包裹   默认  取消  确定(信息条目数)
  final Widget Function(List<T> infoList)? customBottomWidget;

  /// 需要拦截返回时 使用
  final Future<bool> Function()? onWillPop;

  /// 右上角右侧自定义Widget 相册icon 下方 上下排列
  final List<Widget>? rightCustomWidget;

  /// AppBar 右侧的widget  与  rightCustomWidget 互斥
  final WidgetBuilder? titleRightWidget;

  /// 信息框可拖拽headWidget  覆盖infoTitleWidget、infoTitleHeight
  final Widget? infoHeadWidget;

  /// 信息框标题Widget  默认空
  final Widget? infoTitleWidget;
  final double? infoTitleHeight;

  /// 识别解析最小间隔时间 单位毫秒  默认1000， 此值不影响选择图片解析
  final int parseMinInterval;

  /// 超过改数量  触发自动滚动  默认3
  final int autoScrollCount;

  /// 是否是PDA模式  显示UI跟摄像头扫码有差异
  final bool isPDAModel;

  /// 是否初始 scanLock
  final bool initScanLock;

  ///标题
  final Widget? title;

  ///自定义扫码处理, 返回是否向下传递
  final Future<bool> Function(String? scanContent)? onCustomScanHandler;

  ///自定义Sheet View
  final WidgetBuilder? onCustomSheetBuilder;

  @override
  _ContinueScanPageState createState() => _ContinueScanPageState<T>();
}

class _ContinueScanPageState<T> extends State<ContinueScanPage<T>> {
  NDScannerController? controller;
  String _pdaScanId = '';
  bool scanLock = false;
  bool _expand = false;

  /// Controller to scroll or jump to a particular item.
  final ItemScrollController itemScrollController = ItemScrollController();
  final BehaviorSubject<List<T>> _listBehavior = BehaviorSubject();
  List<T> infoList = [];
  late InfoListController _listController;

  /// 大数据模式：true 列表会用Column包裹显示（为确保页面渲染不占用多内存，自定义的条目最好用ListView显示）
  ///  false 列表用ScrollablePositionedList显示（扫码时会自动触发上滚显示）
  bool isBigDataModel = false;

  /// 上次处理扫描结果  用于计算识别间隔时间
  int lastHandleStart = 0;

  bool isPDAModel = false;

  @override
  void initState() {
    infoList = widget.initDataList ?? [];
    scanLock = widget.initScanLock;
    _listController = widget.infoListController;
    _listController.insert = insert;
    _listController.replace = replace;
    _listController.removeList = removeList;
    _listController.remove = remove;
    _listController.removeAt = removeAt;
    _listController.clearList = clearList;
    _listController.isEmpty = isEmpty;
    _listController.listLength = listLength;
    _listController.pauseScan = pauseScan;
    _listController.resumeScan = resumeScan;
    _listController.setScanLock = setScanLock;
    _listController.setBigDataModel = setBigDataModel;
    _listController.defaultScanHandler = (content) {
      _handleScan(content);
    };
    _listController.defaultSheetBuilder = (context) {
      return _contentBody(dragPanelModel: true);
    };
    if (!kIsWeb) {
      //pda扫码监听
      _pdaScanId = PdaScanner.startPDAScan(
          context: context,
          onScanResult: (qrContent) {
            var now = DateTime.now().millisecondsSinceEpoch;
            var interval = now - lastHandleStart;
            if (interval < widget.parseMinInterval) {
              // print('两次间隔小于指定间隔时间 忽略本次结果');
              return;
            }
            if (!scanLock) {
              scanLock = true;
              lastHandleStart = now;
              _handleScan(qrContent);
            }
          });
    }
    isPDAModel = widget.isPDAModel;
    if (isPDAScanModel) {
      isPDAModel = true;
    }
    super.initState();
  }

  @override
  void dispose() {
    if (!kIsWeb && _pdaScanId.isNotEmpty) {
      PdaScanner.stopPDAScan(_pdaScanId);
    }
    _listBehavior.close();
    super.dispose();
  }

  void removeList(List<dynamic> list) {
    list.forEach((infoData) {
      infoList.remove(infoData);
    });
    _updateList();
  }

  void remove(dynamic infoData) {
    infoList.remove(infoData);
    _updateList();
  }

  void removeAt(int index) {
    infoList.removeAt(index);
    _updateList();
  }

  void replace(int index, dynamic data) {
    var infoData = data as T;
    infoList.removeAt(index);
    infoList.insert(index, infoData);
    _updateList();
  }

  void insert(int index, dynamic data) {
    var infoData = data as T;
    infoList.insert(index, infoData);
    _updateList();
  }

  void clearList() {
    infoList.clear();
    _updateList();
  }

  bool isEmpty() {
    return infoList.isEmpty;
  }

  int listLength() {
    return infoList.length;
  }

  void pauseScan() {
    controller?.pause();
  }

  void resumeScan() {
    controller?.resume();
  }

  void setScanLock(bool value) {
    scanLock = value;
  }

  void setBigDataModel(bool bigDataModel) {
    isBigDataModel = bigDataModel;
  }

  void _updateList() {
    if (mounted) {
      _listBehavior.sink.add(infoList);
    }
  }

  Future _handleScan(String? scanResult, {bool showLoading = true}) async {
    if (widget.onCustomScanHandler != null) {
      //如果设置了自定义扫码处理回调，优先使用自定义回调
      var res = await widget.onCustomScanHandler!(scanResult);
      if (res) {
        //根据自定义回调返回值判断是否向下执行默认处理
        return _handleScan2(scanResult);
      } else {
        controller?.resume();
        scanLock = false;
        return Future.value(true);
      }
    } else {
      return _handleScan2(scanResult);
    }
  }

  /// 识别结果处理
  Future _handleScan2(String? scanResult, {bool showLoading = true}) async {
    var getResult = false;
    if (scanResult?.isNotEmpty == true) {
      T? newInfoData =
          await widget.onScanResult(scanResult!, infoList, showLoading);
      if (newInfoData != null) {
        infoList.add(newInfoData);
        getResult = true;
        _updateList();
        // toast(context, '添加成功');
        if (infoList.length > widget.autoScrollCount) {
          // 暂时设置超过3个 开始自动滚动
          await Future.delayed(const Duration(milliseconds: 200));
          await itemScrollController.scrollTo(
              index: infoList.length - 1,
              duration: const Duration(milliseconds: 300),
              curve: Curves.fastOutSlowIn);
        }
      }
    } else {
      toast(context, '识别码内容为空，请确认！');
    }
    scanLock = false;
    return Future.value(getResult);
  }

  Future<bool> _onWillPop() {
    if (widget.onWillPop != null) {
      return widget.onWillPop!();
    }
    return Future.value(true);
  }

  @override
  Widget build(BuildContext context) {
    var padding = MediaQuery.of(context).padding;
    var screenHeight = MediaQuery.of(context).size.height - padding.top;
    var scanHeight = screenHeight * 386 / 812;
    var foldHeight = screenHeight - scanHeight;
    var expandHeight = scanHeight - 56;
    return SafeArea(
      bottom: false,
      child: WillPopScope(
        onWillPop: () => _onWillPop(),
        child: isPDAModel
            ? Container(
                width: double.maxFinite,
                height: double.maxFinite,
                color: Colors.white,
                child: Column(
                  children: [
                    /// 右上角
                    Row(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        _topBackAppBar(),
                        const Spacer(),
                        _middleTitleWidget(),
                        const Spacer(),
                        Padding(
                          padding: const EdgeInsets.only(top: 5.0),
                          child: _rightTitleWidgetPda(),
                        ),
                      ],
                    ),
                    Expanded(
                        child: widget.onCustomSheetBuilder != null
                            ? widget.onCustomSheetBuilder!.call(context)
                            : _contentBody()),
                  ],
                ),
              )
            : Scaffold(
                /// 需要关闭，防止键盘弹出 刷新ScannerWidget Android端会导致拍照预览黑屏
                resizeToAvoidBottomInset: false,
                body: Stack(
                  children: [
                    /// 扫码框
                    NDScannerWidget(
                      // androidSdkInt: androidSdkInt,
                      height: scanHeight,
                      shouldBound: true,
                      continueScan: true,
                      onScannerCreate: (value) {
                        controller = value;
                      },
                      onResult: (String? content) async {
                        var now = DateTime.now().millisecondsSinceEpoch;
                        var interval = now - lastHandleStart;
                        if (interval < widget.parseMinInterval) {
                          // print('两次间隔小于指定间隔时间 忽略本次结果');
                          return;
                        }
                        await controller?.pause();
                        if (!scanLock) {
                          scanLock = true;
                          lastHandleStart = now;
                          await _handleScan(content);
                          scanLock = false;
                        }
                        var parseEnd = DateTime.now().millisecondsSinceEpoch;
                        var delayDuration =
                            widget.parseMinInterval - parseEnd + now;
                        if (delayDuration > 0) {
                          print("二次间隔较短，为${delayDuration}");
                          await Future.delayed(
                              Duration(milliseconds: delayDuration));
                        }
                        await controller?.resume();
                      },
                    ),

                    /// 返回按钮
                    _topBackAppBar(),

                    /// 右上角
                    _rightTitleWidget(),

                    /// 可拖拽信息框
                    _infoDragDropPanel(foldHeight, expandHeight),
                    _middleTitleWidget(),
                  ],
                ),
              ),
      ),
    );
  }

  Widget _topBackAppBar() {
    return SizedBox(
      height: 56,
      child: IconButton(
        icon: CircleAvatar(
          radius: 16,
          backgroundColor: Colors.black.withOpacity(isPDAModel ? 0 : 0.45),
          child: Icon(
            Icons.arrow_back_ios_new_outlined,
            color: isPDAModel ? Theme.of(context).primaryColor : Colors.white,
          ),
        ),
        onPressed: () async {
          var willPop = await _onWillPop();
          if (willPop) {
            Navigator.of(context).pop();
          }
        },
      ),
    );
  }

  /// 中间title
  Widget _middleTitleWidget() {
    return widget.title == null
        ? const SizedBox()
        : Container(
            margin: const EdgeInsets.only(top: 16),
            alignment: Alignment.topCenter,
            child: SafeArea(
              child: DefaultTextStyle(
                  style: TextStyle(
                      fontSize: 16,
                      fontWeight: FontWeight.w600,
                      color: isPDAModel
                          ? Theme.of(context).primaryColor
                          : Colors.white),
                  child: widget.title!),
            ),
          );
  }

  /// 自定义widget  或 从 上下布局的 [相册选择+自定义widgets]
  Widget _rightTitleWidget() {
    var rightActionWidgets = _rightActionWidgets();
    return Positioned(
        right: 10,
        top: 5,
        child: widget.titleRightWidget != null
            ? widget.titleRightWidget!(context)
            : isPDAModel
                ? Row(children: rightActionWidgets)
                : Column(children: rightActionWidgets));
  }

  Widget _rightTitleWidgetPda() {
    var rightActionWidgets = _rightActionWidgets();
    return widget.titleRightWidget != null
        ? widget.titleRightWidget!(context)
        : Row(children: rightActionWidgets);
  }

  List<Widget> _rightActionWidgets() {
    return [
      const SizedBox(height: 4),
      // IconButton(
      //   icon: CircleAvatar(
      //     radius: 16,
      //     backgroundColor: Colors.black.withOpacity(isPDAModel ? 0 : 0.45),
      //     child: ImageIcon(
      //       NCImages.photo_album,
      //       size: 32,
      //       color: isPDAModel ? Theme.of(context).primaryColor : Colors.white,
      //     ),
      //   ),
      //   onPressed: () {
      //     var pickImagesNumber = 0;
      //     var successImageNumber = 0;
      //     PlatformService.pickImages(maxCount: 12).then((value) {
      //       if (value.isEmpty) {
      //         return;
      //       }
      //       NDMethodQRCodeScanner()
      //           .getQrResult(value.map((e) => e.path!).toList())
      //           .then((data) async {
      //         /// 图片地址列表
      //         if (data
      //                 .where((element) =>
      //                     element == null || element.isEmpty == true)
      //                 .length ==
      //             data.length) {
      //           toast(context, '未识别到条形码或二维码');
      //         } else {
      //           /// 批量识别 图片内二维码内容
      //           showHandleProgress(context, () async {
      //             if (data != null && data is List) {
      //               scanLock = true;
      //               await controller?.pause();
      //               pickImagesNumber = value.length;
      //               var j = 0;
      //               for (var i = 0; i < data.length; i++) {
      //                 if (data[i] != null) {
      //                   var res =
      //                       await _handleScan(data[i], showLoading: false);
      //                   if (res) {
      //                     j++;
      //                   }
      //                 }
      //               }
      //               await controller?.resume();
      //               scanLock = false;
      //               successImageNumber = j;
      //             }
      //             return Future.value(100);
      //           }, () {
      //             Completer<BatchHandlerResult> _ = Completer();
      //             Future.delayed(const Duration(milliseconds: 800), () {
      //               if (pickImagesNumber == successImageNumber) {
      //                 _.complete(BatchHandlerResult(success: true));
      //               } else {
      //                 _.complete(BatchHandlerResult(
      //                     success: false,
      //                     errorMessage: S.current
      //                         .p_gjpickmagesumbersuccessmageumberztpclsb(
      //                             pickImagesNumber - successImageNumber)));
      //               }
      //             });
      //             return _.future;
      //           },
      //               tipProgress: S.current.zhengzaishibiezhong,
      //               tipSuccess: S.current.shibiechenggong);
      //         }
      //       }).catchError((error) {});
      //     });
      //   },
      // ),
      if (widget.rightCustomWidget != null) ...widget.rightCustomWidget!,
    ];
  }

  StateSetter? dragPanelState;
  bool keyBoardShow = false;

  void updateDragPanel() {
    Future.delayed(const Duration(milliseconds: 10), () {
      dragPanelState!(() {});
    });
  }

  /// 可拖拽区域 使用Scaffold包裹 开启resizeToAvoidBottomInset
  /// 确保键盘弹出 布局上顶
  Widget _infoDragDropPanel(double foldHeight, double expandHeight) {
    return StatefulBuilder(builder: (context, state) {
      dragPanelState = state;
      var expand = _expand;
      if (keyBoardShow) {
        expand = true;
      }
      return DragDropPanel(
        expand: expand,
        onExpand: (value) {
          _expand = value;
        },
        headWidget: widget.infoHeadWidget,
        titleHeight: widget.infoTitleHeight,
        title: widget.infoTitleWidget,
        foldHeight: foldHeight,
        expandHeight: expandHeight,
        //优先执行自定义sheet view
        child: widget.onCustomSheetBuilder?.call(context) ??
            _contentBody(dragPanelModel: true),
      );
    });
  }

  StreamBuilder<List<T>> _contentBody({bool dragPanelModel = false}) {
    return StreamBuilder<List<T>>(
        initialData: infoList,
        stream: _listBehavior.stream,
        builder: (context, AsyncSnapshot<List<T>> snapshot) {
          var tasks = snapshot.data ?? [];
          Widget bottomWidget;
          if (widget.customBottomWidget != null) {
            bottomWidget = widget.customBottomWidget!(infoList);
          } else {
            bottomWidget = Container(
              padding: EdgeInsets.all(16),
              child: Row(
                children: [
                  SizedBox(
                    width: 100,
                    child: ElevatedButton(
                        onPressed: () {
                          Navigator.pop(context);
                        },
                        child: Text('取消')),
                  ),
                  const SizedBox(width: 12),
                  Expanded(
                    child: FilledButton(
                        onPressed: infoList.isEmpty
                            ? null
                            : () {
                                if (widget.onConfirm != null) {
                                  widget.onConfirm!(infoList);
                                }
                              },
                        child: Text(
                            '确定${infoList.isEmpty ? '' : '(${infoList.length})'}')),
                  )
                ],
              ),
            );
          }
          if (dragPanelModel) {
            if (MediaQuery.of(context).viewInsets.bottom > 0) {
              if (!keyBoardShow) {
                keyBoardShow = true;
                updateDragPanel();
              }
            } else {
              if (keyBoardShow) {
                keyBoardShow = false;
                updateDragPanel();
              }
            }
          }
          Widget sheetBody = widget.initScanLock
              ? const DecoratedBox(
                  // loading页
                  decoration: BoxDecoration(color: Colors.white),
                  child: CircularProgressIndicator(),
                )
              : Container(
                  // 空页面
                  alignment: Alignment.center,
                  child: const Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      SizedBox(height: 45),
                      Icon(
                        Icons.list,
                        size: 32,
                      ),
                    ],
                  ),
                );
          if (widget.customSheetWidget != null) {
            /// 扫码框下面的剩余部分自定义布局
            sheetBody = widget.customSheetWidget!(infoList);
          } else if (tasks.isNotEmpty) {
            if (widget.getInfoItemWidget != null) {
              sheetBody = isBigDataModel
                  ? Column(
                      children: tasks.map((e) {
                        Widget item = widget.getInfoItemWidget!(
                            e, tasks.indexOf(e), tasks.length);
                        if (tasks.last == e) {
                          return Expanded(child: item);
                        }
                        return item;
                      }).toList(),
                    )
                  : ScrollablePositionedList.builder(
                      itemCount: tasks.length,
                      itemBuilder: (context, i) {
                        return widget.getInfoItemWidget!(
                            tasks[i], i, tasks.length);
                      },
                      itemScrollController: itemScrollController,
                    );
            }
          }
          return Scaffold(
            resizeToAvoidBottomInset: true,
            body: sheetBody,
            bottomNavigationBar: widget.customSheetWidget != null
                ? null
                : Container(
                    color: Colors.white, child: SafeArea(child: bottomWidget)),
          );
        });
  }
}
